package com.hnx.admin.aurora.security.utils;

import com.hnx.admin.aurora.web.exception.user.UserInfoException;
import org.springframework.lang.Nullable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.Optional;

/*
创建人： 倔强的头发
创建时间：2025/6/15
功能描述:

*/
public class SecurityUtil {
    // 私有构造器防止实例化
    private SecurityUtil() {
        throw new AssertionError("不允许实例化工具类");
    }
    // 使用静态内部类实现单例的PasswordEncoder (延迟加载+线程安全)
    private static class PasswordEncoderHolder {
        static final PasswordEncoder INSTANCE = new BCryptPasswordEncoder();
    }
    /**
     * 获取当前安全上下文中的认证信息
     * @return 当前认证信息，可能为null
     */
    @Nullable
    public static Authentication getAuthentication() {
        SecurityContext context = SecurityContextHolder.getContext();
        return context != null ? context.getAuthentication() : null;
    }
    /**
     * 获取当前认证的主体信息
     * @return 包装在Optional中的主体对象，避免NPE
     */
    public static Object getPrincipal() {
        return Optional.ofNullable(getAuthentication())
                .map(Authentication::getPrincipal).orElseThrow(UserInfoException::new);
    }
    /**
     * 检查当前用户是否已认证
     * @return 如果用户已认证返回true
     */
    public static boolean isAuthenticated() {
        return Optional.ofNullable(getAuthentication())
                .map(Authentication::isAuthenticated)
                .orElse(false);
    }
    /**
     * 使用BCrypt算法加密密码
     * @param rawPassword 原始密码
     * @return 加密后的密码
     * @throws IllegalArgumentException 如果原始密码为空
     */
    public static String encryptPassword(String rawPassword) {
        if (rawPassword == null || rawPassword.trim().isEmpty()) {
            throw new IllegalArgumentException("原始密码不能为空");
        }
        return PasswordEncoderHolder.INSTANCE.encode(rawPassword);
    }
}
